package cn.iocoder.yudao.module.system.service.chaoshun;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.enums.*;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
import cn.iocoder.yudao.module.system.controller.admin.chaoshun.utils.DxUtils;
import cn.iocoder.yudao.module.system.controller.admin.chaoshun.vo.fsdx.TemplateParamVO;
import cn.iocoder.yudao.module.system.controller.admin.chaoshun.vo.sp.*;
import cn.iocoder.yudao.module.system.dal.dataobject.chaoshun.ChaoshunSpDO;
import cn.iocoder.yudao.module.system.dal.mysql.chaoshun.ChaoshunSpMapper;
import cn.iocoder.yudao.module.system.dal.mysql.chaoshun.ChaoshunXhMapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mzt.logapi.context.LogRecordContext;
import com.mzt.logapi.service.impl.DiffParseFunction;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SP_IMPORT_LIST_IS_EMPTY;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.SP_SPMC_EXISTS;

/**
* @author 16651
* @description 针对表【chaoshun_sp】的数据库操作Service实现
* @createDate 2024-04-14 22:51:35
*/
@Service
public class ChaoshunSpServiceImpl extends ServiceImpl<ChaoshunSpMapper, ChaoshunSpDO>
    implements ChaoshunSpService{

    @Resource
    private ChaoshunSpMapper chaoshunSpMapper;

    @Resource
    private ChaoshunXhMapper chaoshunXhMapper;

    @Resource
    private AdminUserApi adminUserApi;

    @Resource
    private ChaoshunXhService chaoshunXhService;

    @Override
    public PageResult<ChaoshunSpDO> getSpPage(SpPageReqVO reqVO) {
        String lrsjSj = reqVO.getLrsjSj();
        if ("1".equals(lrsjSj)) {
            // 获取今天的日期
            LocalDate today = LocalDate.now();
            // 创建今天的零点时间
            LocalDateTime todayMidnight = today.atTime(LocalTime.MIDNIGHT);
            // 获取明天的日期
            LocalDate tomorrow = today.plusDays(1);
            // 创建明天的零点时间
            LocalDateTime tomorrowMidnight = tomorrow.atTime(LocalTime.MIDNIGHT);
            reqVO.setLrsj(new LocalDateTime[]{todayMidnight, tomorrowMidnight});
        } else if ("2".equals(lrsjSj)) {
            // 获取今天的日期
            LocalDate today = LocalDate.now();
            // 创建今天的零点时间
            LocalDateTime todayMidnight = today.atTime(LocalTime.MIDNIGHT);
            // 获取昨天的日期
            LocalDate tomorrow = today.minusDays(1);
            // 创建昨天的零点时间
            LocalDateTime yesterdayMidnight = tomorrow.atTime(LocalTime.MIDNIGHT);
            reqVO.setLrsj(new LocalDateTime[]{yesterdayMidnight, todayMidnight});
        } else if ("3".equals(lrsjSj)) {
            // 获取当前日期时间
            LocalDateTime now = LocalDateTime.now();

            // 获取本周周一的零点时间
            LocalDateTime mondayThisWeek = now.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY)).with(LocalTime.MIDNIGHT);

            // 获取下周一的零点时间（即在本周周一的基础上加一周）
            LocalDateTime mondayNextWeek = mondayThisWeek.plus(1, ChronoUnit.WEEKS);
            reqVO.setLrsj(new LocalDateTime[]{mondayThisWeek, mondayNextWeek});
        } else if ("4".equals(lrsjSj)) {
            // 获取当前日期
            LocalDate today = LocalDate.now();

            // 获取当前月份的第一天
            LocalDate firstDayOfMonth = today.withDayOfMonth(1);

            // 转换为当天的零点时间
            LocalDateTime startOfMonth = firstDayOfMonth.atStartOfDay();

            // 获取下个月的第一天（下个月的第一天在当前月份的基础上加一个月）
            LocalDate firstDayOfNextMonth = today.withDayOfMonth(1).plusMonths(1);

            // 转换为当天的零点时间
            LocalDateTime startOfNextMonth = firstDayOfNextMonth.atStartOfDay();
            reqVO.setLrsj(new LocalDateTime[]{startOfMonth, startOfNextMonth});
        }
        Integer yhjs = reqVO.getYhjs();
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        AdminUserRespDTO user = adminUserApi.getUser(loginUser.getId());
        String mobile = user.getMobile();
        if (CommonYhjsEnum.QB.getStatus().equals(yhjs)) {
            reqVO.setJqFhdh(mobile);
            reqVO.setJqShdh(mobile);
        } else if (CommonYhjsEnum.FHF.getStatus().equals(yhjs)) {
            reqVO.setJqFhdh(mobile);
        } else if (CommonYhjsEnum.SHF.getStatus().equals(yhjs)) {
            reqVO.setJqShdh(mobile);
        }
        return chaoshunSpMapper.selectPage(reqVO);
    }

    @Override
    public List<ChaoshunSpDO> getYhxxByXm(YhxmVO yhxmVO) {
        return chaoshunSpMapper.getYhxxByXm(yhxmVO);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public PageResult<ChaoshunSpDO> dySpPage(SpPageReqVO reqVO) {
        PageResult<ChaoshunSpDO> chaoshunSpDOPageResult = chaoshunSpMapper.selectDyPage(reqVO);
        List<Long> idList = chaoshunSpDOPageResult.getList().stream().map(ChaoshunSpDO::getId).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(idList)) {
            update(null, new LambdaUpdateWrapper<ChaoshunSpDO>()
                    .set(ChaoshunSpDO::getSfdypz, '1')
                    .in(ChaoshunSpDO::getId, idList));
        }
        return chaoshunSpDOPageResult;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateChaoshunSpStatus(Long id, Integer status) {
        // 更新状态
        ChaoshunSpDO updateObj = new ChaoshunSpDO();
        updateObj.setId(id);
        updateObj.setStatus(status);
        chaoshunSpMapper.updateById(updateObj);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateChaoshunSpSfsm(Long id, Integer sfsm) {
        // 更新状态
        ChaoshunSpDO updateObj = new ChaoshunSpDO();
        updateObj.setId(id);
        updateObj.setSfsm(sfsm);
        chaoshunSpMapper.updateById(updateObj);
    }

    @Override
    public void deleteSp(Long id) {
        // 1 删除物流信息
        chaoshunSpMapper.deleteById(id);

        // 2 记录操作日志上下文
        LogRecordContext.putVariable("deleteSp", id);
    }

    @Override
    public void returnSp(Long id) {
        LambdaUpdateWrapper<ChaoshunSpDO> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(ChaoshunSpDO::getSpzt, CommonSpztEnum.FH.getStatus());
        updateWrapper.set(ChaoshunSpDO::getSffh, CommonSfEnum.ENABLE.getStatus());
        updateWrapper.eq(ChaoshunSpDO::getId, id);
        // 1 返货
        chaoshunSpMapper.update(updateWrapper);

        // 2 记录操作日志上下文
        LogRecordContext.putVariable("returnSp", id);
    }

    @Override
    public void delaySp(Long id) {
        ChaoshunSpDO spDO = chaoshunSpMapper.selectById(id);
        LambdaUpdateWrapper<ChaoshunSpDO> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.set(ChaoshunSpDO::getSpzt, CommonSpztEnum.YCZH.getStatus());
        updateWrapper.set(ChaoshunSpDO::getYccs, spDO.getYccs() + 1);
        updateWrapper.eq(ChaoshunSpDO::getId, id);
        // 1 延迟装货
        chaoshunSpMapper.update(updateWrapper);

        // 2 记录操作日志上下文
        LogRecordContext.putVariable("delaySp", id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String createChaoshunSp(ChaoshunSpSaveReqVO createReqVO) {
        String type = createReqVO.getType();
        LocalDateTime blrq = createReqVO.getBlrq();
        Integer sflx = createReqVO.getSflx();
        // 1.1 插入商品
        ChaoshunSpDO spDO = BeanUtils.toBean(createReqVO, ChaoshunSpDO.class);
        // 若是补录数据，则设置补录日期
        if ("supply".equals(type)) {
            spDO.setLrsj(blrq);
            spDO.setSfbl(CommonSfEnum.ENABLE.getStatus());
        } else {
            spDO.setLrsj(LocalDateTime.now());
        }
        spDO.setStatus(CommonStatusEnum.DISABLE.getStatus()); // 默认是
        if (ObjectUtil.isNull(spDO.getSfsm())) {
            spDO.setSfsm(CommonSfEnum.DISABLE.getStatus());
        }
        spDO.setYdh(getYdh(type, blrq));
        if (CommonSflxEnum.WS.getStatus().equals(sflx)) {
            spDO.setSpzt(CommonSpztEnum.KDDSH.getStatus());
        } else if (CommonSflxEnum.WJ.getStatus().equals(sflx)) {
            spDO.setSpzt(CommonSpztEnum.KDDFH.getStatus());
        } else {
            spDO.setSpzt(CommonSpztEnum.TJ.getStatus());
        }
        spDO.setSffh(CommonSfEnum.DISABLE.getStatus());
        chaoshunSpMapper.insert(spDO);

        // 3. 记录操作日志上下文
        LogRecordContext.putVariable("chaoshunsp", spDO);
        return spDO.getYdh();
    }

    private String getYdh(String type, LocalDateTime blrq) {
        String rq;
        // 若是补录数据，则单号日期用补录日期
        if ("supply".equals(type)) {
            rq = DateUtil.format(blrq, "yyyyMMdd");
        } else {
            rq = DateUtil.format(new Date(), "yyyyMMdd");
        }
        String xh = getTableXh("chaoshun_sp", rq) + "";
        int zeroNum = 6 - xh.length();
        for (int i = 0; i < zeroNum; i++) {
            rq += "0";
        }
        return rq + xh;
    }

    /**
     * 获取业务序号
     * @return 序号
     */
    private int getTableXh(String table, String rq) {
        String xhId = table + "_" + rq;
        Integer xhInteger = chaoshunXhMapper.getXh(xhId);
        int resultNum;
        int xh;
        if (ObjectUtil.isNull(xhInteger)) {
            xh = 1;
            resultNum = chaoshunXhMapper.insertXh(xh, xhId);
        } else {
            xh = xhInteger + 1;
            resultNum = chaoshunXhMapper.updateXh(xh, xhId);
        }
        if (resultNum > 0) {
            return xh;
        } else {
            return getTableXh(table, rq);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateChaoshunSp(ChaoshunSpSaveReqVO updateReqVO) {
        // 1.1 更新用户
        ChaoshunSpDO spDO = BeanUtils.toBean(updateReqVO, ChaoshunSpDO.class);
        chaoshunSpMapper.updateById(spDO);

        // 3. 记录操作日志上下文
        LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, updateReqVO);
        LogRecordContext.putVariable("chaoshunsp", spDO);
    }

    @Override
    public ChaoshunSpDO getChaoshunSp(Long id) {
        return chaoshunSpMapper.selectById(id);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void fsdx(List<Long> idList) {
        List<ChaoshunSpDO> spList = chaoshunSpMapper.selectList(ChaoshunSpDO::getId, idList);
        List<String> sjhmList = new ArrayList<>();
        List<String> signList = new ArrayList<>();
        String templateCode = "SMS_465423086";
        List<TemplateParamVO> paramList = new ArrayList<>();
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日"); // 例如："2024年04月19日"
        // 使用formatter来格式化date
        String nowDate = LocalDate.now().format(formatter);
        for (ChaoshunSpDO spDO : spList) {
            // 剔除已发送
            if (spDO.getStatus() == 0) {
                continue;
            }
            String sjhm = spDO.getShdh();
            // 剔除手机号为空
            if (StrUtil.isEmpty(sjhm)) {
                continue;
            }
            sjhmList.add(sjhm);
            signList.add("邳州市北斗恒昇物流");
            TemplateParamVO templateParamVO = new TemplateParamVO();
//            templateParamVO.setCommodity(spDO.getSpmc());
            templateParamVO.setCommodity("朝顺快递");
            templateParamVO.setTime(nowDate);
            templateParamVO.setPlace("文苑路与中山路交叉路口立交桥下面最里面(朝顺物流快递点)");
            templateParamVO.setCode("1234");
            templateParamVO.setSjhm("18068485869");
            paramList.add(templateParamVO);
        }
        DxUtils.fsdx(sjhmList, signList, templateCode, paramList);
        chaoshunSpMapper.update(Wrappers.<ChaoshunSpDO>lambdaUpdate().in(ChaoshunSpDO::getId, idList).set(ChaoshunSpDO::getStatus, 0));
    }

    @Override
    @Transactional(rollbackFor = Exception.class) // 添加事务，异常则回滚所有导入
    public SpImportRespVO importSpList(List<SpImportExcelVO> importSps, boolean isUpdateSupport) {
        if (CollUtil.isEmpty(importSps)) {
            throw exception(SP_IMPORT_LIST_IS_EMPTY);
        }
        SpImportRespVO respVO = SpImportRespVO.builder().createSpmcs(new ArrayList<>())
                .updateSpmcs(new ArrayList<>()).failureSpmcs(new LinkedHashMap<>()).build();
        importSps.forEach(importSp -> {
            // 判断如果不存在，在进行插入
            ChaoshunSpDO existSp = chaoshunSpMapper.selectById(importSp.getId());
            if (ObjectUtil.isNull(importSp.getStatus())) {
                importSp.setStatus(CommonSfEnum.DISABLE.getStatus());
            }
            if (ObjectUtil.isNull(importSp.getSfsm())) {
                importSp.setSfsm(CommonSfEnum.DISABLE.getStatus());
            }
            if (existSp == null) {
                chaoshunSpMapper.insert(BeanUtils.toBean(importSp, ChaoshunSpDO.class)); // 设置默认密码及空岗位编号数组
                respVO.getCreateSpmcs().add(importSp.getSpmc());
                return;
            }
            // 如果存在，判断是否允许更新
            if (!isUpdateSupport) {
                respVO.getFailureSpmcs().put(importSp.getSpmc(), SP_SPMC_EXISTS.getMsg());
                return;
            }

            ChaoshunSpDO updateSp = BeanUtils.toBean(importSp, ChaoshunSpDO.class);
            updateSp.setId(existSp.getId());
            chaoshunSpMapper.updateById(updateSp);
            respVO.getUpdateSpmcs().add(importSp.getSpmc());
        });
        return respVO;
    }


}




